package com.jolink.omiis.wechat.message;

import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.jolink.omiis.wechat.BusinessEntry;
import com.jolink.omiis.wechat.WeChatContext;
import com.jolink.omiis.wechat.api.CSMessageBuilder;
import com.jolink.omiis.wechat.api.ICustomerService;
import com.jolink.omiis.wechat.api.IMaterialApi;
import com.jolink.omiis.wechat.api.IRobotApi;
import com.jolink.omiis.wechat.api.IUserOperationApi;
import com.jolink.omiis.wechat.inner.ConversationType;
import com.jolink.omiis.wechat.inner.IOmiisMessager;
import com.jolink.omiis.wechat.keys.IPreferences;
import com.jolink.omiis.wechat.message.bean.request.ImageMessageRequest;
import com.jolink.omiis.wechat.message.bean.request.MessageRequestBase;
import com.jolink.omiis.wechat.message.bean.request.SubscribeEventRequest;
import com.jolink.omiis.wechat.message.bean.request.TextMessageRequest;
import com.jolink.omiis.wechat.message.bean.request.UnsubscribeEventRequest;
import com.jolink.omiis.wechat.message.bean.request.VideoMessageRequest;
import com.jolink.omiis.wechat.message.bean.request.VoiceMessageRequest;
import com.jolink.omiis.wechat.message.type.EventType;
import com.jolink.omiis.wechat.message.type.MessageType;
import com.jolink.omiis.wechat.message.type.SatisfactionType;
import com.jolink.omiis.wechat.message.type.SenderRole;
import com.jolink.omiis.wechat.mongo.IMongodbProcessor;
import com.jolink.omiis.wechat.outer.WeChatResponse;
import com.jolink.omiis.wechat.redis.IRedisProcessor;
import com.jolink.omiis.wechat.util.CacheUtil;
import com.jolink.omiis.wechat.util.DateUtil;
import com.jolink.omiis.wechat.util.FileUtil;
import com.jolink.omiis.wechat.util.GsonUtil;
import com.jolink.omiis.wechat.util.SFTPUtil;
import com.jolink.omiis.wechat.util.WeChatConfiguration;
import com.jolink.omiis.wechat.util.XmlParser;

/**
 * 处理微信用户信息请求Handler
 * 
 * @author WangYanqing
 *
 */
@Component
public class DefaultMessageHandler extends AbstractMessageHandler implements IMessageHandler {
	public DefaultMessageHandler() {
	}

	private static String filterChar = "1";

	private static final Logger logger = LoggerFactory.getLogger(DefaultMessageHandler.class);

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.jolink.omiis.wechat.message.IMessageHandler#handleMessage()
	 */
	@Override
	public WeChatResponse handleMessage() throws Exception {
		long t1 = System.currentTimeMillis();
		WeChatResponse wr = createDefaultWeChatResponse();
		String reqestMessage = getReqMessage();
		Document doc = XmlParser.str2Xml(reqestMessage);
		Element msgTypeElement = (Element) doc.selectSingleNode("/xml/MsgType");
		Element fromUserNameElement = (Element) doc.selectSingleNode("/xml/FromUserName");
		String fromUserName = fromUserNameElement.getTextTrim();
		MessageType mt = MessageType.valueOf(msgTypeElement.getTextTrim().toUpperCase());
		try {
			setMessageType(mt);
		} catch (Exception e) {
			logger.error("初始化MessageRequestBase发生错误，消息类型：{}，异常消息：{}。", mt.getValue(), e.getMessage());
			return wr;
		}
		logger.info("开始处理微信用户：{}请求，消息类型：{}，内容：{}。", fromUserName, mt.getValue(), reqestMessage);
		switch (mt) {
		case TEXT:
			processTextRequest();
			break;
		case VIDEO:
			processVideoRequest();
			break;
		case SHORTVIDEO:
			processShortVideoRequest();
			break;
		case IMAGE:
			processImageRequest();
			break;
		case LOCATION:
			processLocationRequest();
			break;
		case LINK:
			processLinkRequest();
			break;
		case EVENT:
			Element eventTypeE = (Element) doc.selectSingleNode("/xml/Event");
			String eventTypeStr = eventTypeE.getTextTrim();
			EventType et = EventType.valueOf(eventTypeStr.toUpperCase());
			logger.info("处理微信用户：{}请求，事件类型：{}。", fromUserName, et.getValue());
			switch (et) {
			case SUBSCRIBE:
				processSubscribeRequest();
				break;
			case UNSUBSCRIBE:
				processUnsubscribeRequest();
				break;
			default:
				break;
			}
			break;
		case VOICE:
			processVoiceRequest();
			break;
		default:
			break;
		}
		// TODO WeChatResponse 可能会废弃，微信用户信息采用异步处理，后续做修正 20160908 by wangyq
		long t2 = System.currentTimeMillis();
		logger.info("处理微信用户：{}请求完成，耗时：{}毫秒。", fromUserName, (t2 - t1));
		return wr;
	}

	/**
	 * 
	 * 检查微信用户是否再会话当中
	 * 
	 * @param userBaseInfo
	 * @return
	 */
	private static boolean checkInSession(Map<String, String> userBaseInfo) {
		String sessionIdKey = IPreferences.SESSION_ID_KEY;
		if (!userBaseInfo.containsKey(sessionIdKey)) {
			return false;
		}
		String sessionId = userBaseInfo.get(sessionIdKey);
		if (StringUtils.isEmpty(sessionId)) {
			return false;
		}
		return true;
	}

	/**
	 * 处理视频请求
	 */
	private void processVideoRequest() {
		long t1 = System.currentTimeMillis();
		VideoMessageRequest request = (VideoMessageRequest) getMessageRequestBase();
		String open_id = request.getFromUserName();
		logger.info("开始处理微信用户：{}视频请求：", open_id);
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		IMongodbProcessor mongodbProcessor = getContext().getServiceUtil().getMongodbProcessor();// SpringContextUtil.getBean(IMongodbProcessor.class);
		ICustomerService cs = getContext().getServiceUtil().getCustomerService();// SpringContextUtil.getBean(ICustomerService.class);
		IMaterialApi materialApi = getContext().getServiceUtil().getMaterialApi();// SpringContextUtil.getBean(IMaterialApi.class);
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		try {
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(open_id)));
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		// step-1 客户入队
		if (StringUtils.isEmpty(sessionId)) {
			userSessionInfo.putAll(enqueue(request.getToUserName(), request.getFromUserName()));
		} else {
			try {
				userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}

		if (checkInSession(userBaseInfo)) {
			try {
				userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}

			String mediaId = request.getMediaId();
			String downloadPath = WeChatConfiguration.getIngleton().getValue("TENCENT_MATERIAL_DOWN_PATH");
			String app_id = userSessionInfo.get("app_id");
			// TODO需要针对MediaInfo做异常处理
			Map<String, String> mediaInfo = materialApi.downloadTempMaterial(app_id, mediaId);
			// TODO
			logger.info("下载微信用户：{}，视频素材结果：{}。", open_id, mediaInfo);
			String fileName = mediaInfo.get("fileName");
			String tempPath = mediaInfo.get("tempPath");
			String multiMediaPath = FileUtil.getMultiMediaPath();
			try {
				// SFTPUtil.put(tempPath + File.separator + fileName,
				// WeChatConfiguration.getIngleton().getValue("OMIIS_MATERIAL_UPLOAD_PATH"));
				SFTPUtil.put(tempPath + File.separator + fileName, multiMediaPath);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			// String fileUrl =
			// WeChatConfiguration.getIngleton().getValue("OMIIS_MATERIAL_BASE_URL")
			// + fileName;
			String fileUrl = FileUtil.getMultiMediaFullPath(fileName);
			logger.info("腾讯视频素材下载路径：{}，mediaId：{}，fileName：{}，MultiMediaPath：{}，全媒体视频URL：{}。", downloadPath, mediaId,
					fileName, multiMediaPath, fileUrl);
			String conversation_type = userSessionInfo.get("conversation_type");
			logger.info("微信用户：{}，会话状态：{}，会话信息：{}。", request.getFromUserName(), conversation_type, userSessionInfo);
			ConversationType ct = ConversationType.valueOf(conversation_type.toUpperCase());
			userSessionInfo.put("previous_message_time", DateUtil.getCurrentDate());
			userSessionInfo.put("previous_message_timestamp", DateUtil.getCurrentTimeMillis());
			try {
				redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			switch (ct) {
			case RESOURCE_REQUEST:
			case EVENT_WAITING:
			case EVENT_WAITING_REPLY:
				try {
					Map<String, Object> mongoMessage = new HashMap<>();
					mongoMessage.put("userId", userSessionInfo.get("user_id"));
					mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
					mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
					mongoMessage.put("question", fileUrl);
					mongoMessage.put("robotResponse", "");
					mongoMessage.put("sendTime", new Date());
					mongoMessage.put("msgType", MessageType.VIDEO.toString());
					mongoMessage.put("receiveTime", mongoMessage.get("sendTime"));
					mongoMessage.put("createDate", mongoMessage.get("sendTime"));
					mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}

				if (!userSessionInfo.containsKey("transferCounter")) {
					userSessionInfo.put("transferCounter", String.valueOf(1));
					try {
						redis.hmset(CacheUtil.getSessionKey(userBaseInfo.get("session_id")), userSessionInfo);
						logger.info("微信用户：{}，重复发送继续等待请求，更新转接人工统计次数，当前次数：{}。", request.getFromUserName(),
								userSessionInfo);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					cs.send(userBaseInfo.get("app_id"),
							CSMessageBuilder.createMessage(userSessionInfo.get("open_id"), MessageType.TEXT.getValue(),
									getContext().getServiceUtil().getExpression().getTransferAgentTip2()));
					try {
						Map<String, Object> mongoMessage = new HashMap<>();
						mongoMessage.put("userId", userSessionInfo.get("user_id"));
						mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
						mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
						mongoMessage.put("question", "");
						mongoMessage.put("receiveTime", new Date());
						mongoMessage.put("sendTime", mongoMessage.get("receiveTime"));
						JsonObject root = new JsonObject();
						root.addProperty("rspCode", "0");
						root.addProperty("rspMsg", "");
						root.addProperty("rspType", "2");
						root.addProperty("conversationId", userSessionInfo.get("conversationId"));
						root.addProperty("singleNode", "");
						JsonObject singleNode = new JsonObject();
						root.add("singleNode", singleNode);
						singleNode.addProperty("type", "1");
						singleNode.addProperty("content",
								getContext().getServiceUtil().getExpression().getTransferAgentTip2());
						mongoMessage.put("robotResponse", root.toString());
						mongoMessage.put("createDate", mongoMessage.get("receiveTime"));
						mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}

				if (ConversationType.EVENT_WAITING.getValue().equals(conversation_type)
						|| ConversationType.EVENT_WAITING_REPLY.getValue().equals(conversation_type)) {
					Map<String, String> deltaSessionInfo = new HashMap<String, String>();
					deltaSessionInfo.put("openId", request.getFromUserName());
					deltaSessionInfo.put("direction", "customer");
					deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
					getContext().getServiceUtil().getSessionManager().updateSession(request.getFromUserName(),
							deltaSessionInfo);
				}
				break;
			case EVENT_TALK:
				if (!userSessionInfo.containsKey("session_valid_flag")) {
					logger.info("将微信用户{}，会话ID：{}设置为有效会话。", open_id, sessionId);
					userSessionInfo.put("session_valid_flag", Boolean.TRUE.toString());
					try {
						redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}
				Map<String, String> msg = createOmiisMessage(userSessionInfo, MessageType.VIDEO.toString(), fileUrl);
				getMessager().sendMessage(msg);
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("openId", open_id);
				deltaSessionInfo.put("direction", "customer");
				deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				getContext().getServiceUtil().getSessionManager().updateSession(open_id, deltaSessionInfo);
				break;
			case ROBOT:
				processRobot(request.getFromUserName(), request.getToUserName(), fileUrl);
				break;
			default:
				logger.info("微信用户：{}，基本信息：{}，当前状态：{}，暂不支持处理。", request.getFromUserName(), userBaseInfo,
						userSessionInfo);
				break;
			}
		} else {
			logger.error("微信用户：{}加入队列失败。", request.getFromUserName());
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理微信用户：{}，视频请求完成，耗时：{}毫秒。", request.getFromUserName(), (t2 - t1));
	}

	/**
	 * 处理小视频请求
	 */
	private void processShortVideoRequest() {
		processVideoRequest();
	}

	/**
	 * 处理音频请求
	 */
	private void processVoiceRequest() {
		VoiceMessageRequest request = (VoiceMessageRequest) getMessageRequestBase();
		long t1 = System.currentTimeMillis();
		String open_id = request.getFromUserName();
		logger.info("开始处理微信用户：{}音频请求：", open_id);
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();// SpringContextUtil.getBean(IRedisProcessor.class);
		IMongodbProcessor mongodbProcessor = getContext().getServiceUtil().getMongodbProcessor();// SpringContextUtil.getBean(IMongodbProcessor.class);
		ICustomerService cs = getContext().getServiceUtil().getCustomerService();// SpringContextUtil.getBean(ICustomerService.class);
		IMaterialApi materialApi = getContext().getServiceUtil().getMaterialApi();// SpringContextUtil.getBean(IMaterialApi.class);
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		try {
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(open_id)));
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}

		String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		// step-1 客户入队
		if (StringUtils.isEmpty(sessionId)) {
			userSessionInfo.putAll(enqueue(request.getToUserName(), request.getFromUserName()));
		} else {
			try {
				userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}

		if (checkInSession(userBaseInfo)) {
			String session_id = userBaseInfo.get("session_id");
			try {
				userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(session_id)));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			String conversation_type = userSessionInfo.get("conversation_type");
			logger.info("微信用户：{}，会话状态：{}，会话信息：{}。", request.getFromUserName(), conversation_type, userSessionInfo);
			ConversationType ct = ConversationType.valueOf(conversation_type.toUpperCase());

			userSessionInfo.put("previous_message_time", DateUtil.getCurrentDate());
			userSessionInfo.put("previous_message_timestamp", DateUtil.getCurrentTimeMillis());
			try {
				redis.hmset(CacheUtil.getSessionKey(session_id), userSessionInfo);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			String mediaId = request.getMediaId();
			String downloadPath = getContext().getServiceUtil().getConfiguration()
					.getValue("TENCENT_MATERIAL_DOWN_PATH");
			String app_id = userSessionInfo.get("app_id");
			Map<String, String> mediaInfo = materialApi.downloadTempMaterial(app_id, mediaId);
			logger.info("下载微信用户：{}，音频素材结果：{}。", open_id, mediaInfo);
			String fileName = mediaInfo.get("fileName");
			String tempPath = mediaInfo.get("tempPath");
			String multiMediaPath = FileUtil.getMultiMediaPath();
			// logger.info("腾讯素材下载路径：{}，mediaId：{}，fileName：{}", downloadPath,
			// mediaId, fileName);
			try {
				SFTPUtil.put(tempPath + File.separator + fileName, multiMediaPath);
				// SFTPUtil.put(tempPath + File.separator + fileName,
				// WeChatConfiguration.getIngleton().getValue("OMIIS_MATERIAL_UPLOAD_PATH"));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			// String fileUrl =
			// WeChatConfiguration.getIngleton().getValue("OMIIS_MATERIAL_BASE_URL")
			// + fileName;
			String fileUrl = FileUtil.getMultiMediaFullPath(fileName);
			logger.info("腾讯音频素材下载路径：{}，mediaId：{}，fileName：{}，MultiMediaPath：{}，全媒体音频URL：{}。", downloadPath, mediaId,
					fileName, multiMediaPath, fileUrl);
			String fileUrlWithDuration = fileUrl + "^" + mediaInfo.get("duration");
			// Map<String, String> msg = createOmiisMessage(userSessionInfo,
			// "AUDIO",
			// fileUrl + "^" + mediaInfo.get("duration"));
			Map<String, String> msg = createOmiisMessage(userSessionInfo, "AUDIO", fileUrlWithDuration);
			switch (ct) {
			case RESOURCE_REQUEST:
			case EVENT_WAITING:
			case EVENT_WAITING_REPLY:
				try {
					Map<String, Object> mongoMessage = new HashMap<>();
					mongoMessage.put("userId", userSessionInfo.get("user_id"));
					mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
					mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
					mongoMessage.put("question", fileUrlWithDuration);
					mongoMessage.put("robotResponse", "");
					mongoMessage.put("sendTime", new Date());
					mongoMessage.put("msgType", MessageType.AUDIO.toString());
					mongoMessage.put("receiveTime", mongoMessage.get("sendTime"));
					mongoMessage.put("createDate", mongoMessage.get("sendTime"));
					mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}

				if (!userSessionInfo.containsKey("transferCounter")) {
					userSessionInfo.put("transferCounter", String.valueOf(1));
					try {
						redis.hmset(CacheUtil.getSessionKey(userBaseInfo.get("session_id")), userSessionInfo);
						logger.info("微信用户：{}，重复发送继续等待请求，更新转接人工统计次数，当前次数：{}。", request.getFromUserName(),
								userSessionInfo);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					cs.send(userBaseInfo.get("app_id"),
							CSMessageBuilder.createMessage(userSessionInfo.get("open_id"), MessageType.TEXT.getValue(),
									getContext().getServiceUtil().getExpression().getTransferAgentTip2()));
					try {
						Map<String, Object> mongoMessage = new HashMap<>();
						mongoMessage.put("userId", userSessionInfo.get("user_id"));
						mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
						mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
						mongoMessage.put("question", "");
						mongoMessage.put("receiveTime", new Date());
						mongoMessage.put("sendTime", mongoMessage.get("receiveTime"));
						// JsonObject root = new JsonObject();
						// root.addProperty("rspCode", "0");
						// root.addProperty("rspMsg", "");
						// root.addProperty("rspType", "2");
						// root.addProperty("conversationId",
						// userSessionInfo.get("conversationId"));
						// root.addProperty("singleNode", "");
						// JsonObject singleNode = new JsonObject();
						// root.add("singleNode", singleNode);
						// singleNode.addProperty("type", "1");
						// singleNode.addProperty("content",
						// getContext().getServiceUtil().getExpression().getTransferAgentTip2());

						JsonObject root = new JsonObject();
						root.addProperty("protocolId", "6");
						root.addProperty("result", "0");
						root.addProperty("sendTime", "0");
						root.addProperty("answerTypeId", "1");
						JsonObject singleNode = new JsonObject();
						singleNode.addProperty("standardQuestionId", "100");
						singleNode.addProperty("answerMsg",
								getContext().getServiceUtil().getExpression().getTransferAgentTip2());
						singleNode.addProperty("standardQuestion", "");
						singleNode.addProperty("isRichText", "0");
						singleNode.add("list", null);
						root.add("singleNode", singleNode);
						root.add("vagueNode", null);
						mongoMessage.put("robotResponse", root.toString());
						mongoMessage.put("createDate", mongoMessage.get("receiveTime"));
						mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					if (ConversationType.EVENT_WAITING.getValue().equals(conversation_type)
							|| ConversationType.EVENT_WAITING_REPLY.getValue().equals(conversation_type)) {
						Map<String, String> deltaSessionInfo = new HashMap<String, String>();
						deltaSessionInfo.put("openId", request.getFromUserName());
						deltaSessionInfo.put("direction", "customer");
						deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
						getContext().getServiceUtil().getSessionManager().updateSession(request.getFromUserName(),
								deltaSessionInfo);
					}
				}
				break;
			case EVENT_TALK:
				if (!userSessionInfo.containsKey("session_valid_flag")) {
					logger.info("将微信用户{}，会话ID：{}设置为有效会话。", open_id, session_id);
					userSessionInfo.put("session_valid_flag", Boolean.TRUE.toString());
					try {
						redis.hmset(CacheUtil.getSessionKey(session_id), userSessionInfo);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}
				getMessager().sendMessage(msg);
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("openId", open_id);
				deltaSessionInfo.put("direction", "customer");
				deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				getContext().getServiceUtil().getSessionManager().updateSession(open_id, deltaSessionInfo);
				break;
			case ROBOT:
				processRobot(request.getFromUserName(), request.getToUserName(), fileUrlWithDuration);
				break;
			default:
				break;
			}
		} else {
			// do nothing
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理微信用户：{}，音频请求完成，耗时：{}毫秒。", request.getFromUserName(), (t2 - t1));
	}

	/**
	 * 处理图片请求
	 */
	private void processImageRequest() {
		ImageMessageRequest request = (ImageMessageRequest) getMessageRequestBase();
		long t1 = System.currentTimeMillis();
		String open_id = request.getFromUserName();
		logger.info("开始处理微信用户：{}图片请求：", open_id);
		IMongodbProcessor mongodbProcessor = getContext().getServiceUtil().getMongodbProcessor();
		ICustomerService cs = getContext().getServiceUtil().getCustomerService();
		IMaterialApi materialApi = getContext().getServiceUtil().getMaterialApi();
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();// SpringContextUtil.getBean(IRedisProcessor.class);
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		try {
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(open_id)));
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}

		String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		// step-1 客户入队
		if (StringUtils.isEmpty(sessionId)) {
			userSessionInfo.putAll(enqueue(request.getToUserName(), request.getFromUserName()));
		} else {
			try {
				userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}

		if (checkInSession(userBaseInfo)) {
			String session_id = userBaseInfo.get("session_id");
			try {
				userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(session_id)));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			userSessionInfo.put("previous_message_time", DateUtil.getCurrentDate());
			userSessionInfo.put("previous_message_timestamp", DateUtil.getCurrentTimeMillis());
			try {
				redis.hmset(CacheUtil.getSessionKey(session_id), userSessionInfo);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			String conversation_type = userSessionInfo.get("conversation_type");
			logger.info("微信用户：{}，会话状态：{}，会话信息：{}。", request.getFromUserName(), userSessionInfo, conversation_type);
			ConversationType ct = ConversationType.valueOf(conversation_type.toUpperCase());
			userSessionInfo.put("previous_message_time", DateUtil.getCurrentDate());
			userSessionInfo.put("previous_message_timestamp", DateUtil.getCurrentTimeMillis());
			try {
				redis.hmset(CacheUtil.getSessionKey(session_id), userSessionInfo);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			String mediaId = request.getMediaId();
			String app_id = userSessionInfo.get("app_id");
			Map<String, String> mediaInfo = materialApi.downloadTempMaterial(app_id, mediaId);
			logger.info("下载微信用户：{}，图片素材结果：{}。", open_id, mediaInfo);
			String fileName = mediaInfo.get("fileName");
			String tempPath = mediaInfo.get("tempPath");
			String multiMediaPath = FileUtil.getMultiMediaPath();
			String downloadPath = WeChatConfiguration.getIngleton().getValue("TENCENT_MATERIAL_DOWN_PATH");
			// logger.info("腾讯素材下载路径：{}，mediaId：{}，fileName：{}。", tempPath,
			// mediaId, fileName);
			try {
				SFTPUtil.put(tempPath + File.separator + fileName, multiMediaPath);
				// SFTPUtil.put(tempPath + File.separator + fileName,
				// getContext().getServiceUtil().getConfiguration().getValue("OMIIS_MATERIAL_UPLOAD_PATH"));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			// String fileUrl = multiMediaPath;
			String fileUrl = FileUtil.getMultiMediaFullPath(fileName);
			// String fileUrl =
			// getContext().getServiceUtil().getConfiguration().getValue("OMIIS_MATERIAL_BASE_URL")
			// + fileName;
			logger.info("腾讯图片素材下载路径：{}，mediaId：{}，fileName：{}，MultiMediaPath：{}，全媒体图片URL：{}。", downloadPath, mediaId,
					fileName, multiMediaPath, fileUrl);
			Map<String, String> msg = new HashMap<String, String>();
			msg.putAll(userSessionInfo);
			msg.putAll(createOmiisMessage(userSessionInfo, MessageType.IMAGE.toString(), fileUrl));

			switch (ct) {
			case RESOURCE_REQUEST:
			case EVENT_WAITING:
			case EVENT_WAITING_REPLY:
				try {
					Map<String, Object> mongoMessage = new HashMap<>();
					mongoMessage.put("userId", userSessionInfo.get("user_id"));
					mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
					mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
					mongoMessage.put("question", fileUrl);
					mongoMessage.put("robotResponse", "");
					mongoMessage.put("sendTime", new Date());
					mongoMessage.put("msgType", MessageType.IMAGE.toString());
					mongoMessage.put("receiveTime", mongoMessage.get("sendTime"));
					mongoMessage.put("createDate", mongoMessage.get("sendTime"));
					mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}

				if (!userSessionInfo.containsKey("transferCounter")) {
					userSessionInfo.put("transferCounter", String.valueOf(1));
					try {
						redis.hmset(CacheUtil.getSessionKey(userBaseInfo.get("session_id")), userSessionInfo);
						logger.info("微信用户：{}，重复发送继续等待请求，更新转接人工统计次数，当前次数：{}。", request.getFromUserName(),
								userSessionInfo);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					cs.send(userBaseInfo.get("app_id"),
							CSMessageBuilder.createMessage(userSessionInfo.get("open_id"), MessageType.TEXT.getValue(),
									getContext().getServiceUtil().getExpression().getTransferAgentTip2()));
					try {
						Map<String, Object> mongoMessage = new HashMap<>();
						mongoMessage.put("userId", userSessionInfo.get("user_id"));
						mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
						mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
						mongoMessage.put("question", "");
						mongoMessage.put("receiveTime", new Date());
						mongoMessage.put("sendTime", mongoMessage.get("receiveTime"));
						// JsonObject root = new JsonObject();
						// root.addProperty("rspCode", "0");
						// root.addProperty("rspMsg", "");
						// root.addProperty("rspType", "2");
						// root.addProperty("conversationId",
						// userSessionInfo.get("conversationId"));
						// root.addProperty("singleNode", "");
						// JsonObject singleNode = new JsonObject();
						// root.add("singleNode", singleNode);
						// singleNode.addProperty("type", "1");
						// singleNode.addProperty("content",
						// getContext().getServiceUtil().getExpression().getTransferAgentTip2());
						JsonObject root = new JsonObject();
						root.addProperty("protocolId", "6");
						root.addProperty("result", "0");
						root.addProperty("sendTime", "0");
						root.addProperty("answerTypeId", "1");
						JsonObject singleNode = new JsonObject();
						singleNode.addProperty("standardQuestionId", "100");
						singleNode.addProperty("answerMsg",
								getContext().getServiceUtil().getExpression().getTransferAgentTip2());
						singleNode.addProperty("standardQuestion", "");
						singleNode.addProperty("isRichText", "0");
						singleNode.add("list", null);
						root.add("singleNode", singleNode);
						root.add("vagueNode", null);
						mongoMessage.put("robotResponse", root.toString());
						mongoMessage.put("createDate", mongoMessage.get("receiveTime"));
						mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}

				if (ConversationType.EVENT_WAITING.getValue().equals(conversation_type)
						|| ConversationType.EVENT_WAITING_REPLY.getValue().equals(conversation_type)) {
					Map<String, String> deltaSessionInfo = new HashMap<String, String>();
					deltaSessionInfo.put("openId", request.getFromUserName());
					deltaSessionInfo.put("direction", "customer");
					deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
					getContext().getServiceUtil().getSessionManager().updateSession(request.getFromUserName(),
							deltaSessionInfo);
				}
				break;
			case EVENT_TALK:
				getMessager().sendMessage(msg);
				if (!userSessionInfo.containsKey("session_valid_flag")) {
					logger.info("将微信用户{}，会话ID：{}设置为有效会话。", open_id, session_id);
					userSessionInfo.put("session_valid_flag", Boolean.TRUE.toString());
					try {
						redis.hmset(CacheUtil.getSessionKey(session_id), userSessionInfo);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("openId", open_id);
				deltaSessionInfo.put("direction", "customer");
				deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				getContext().getServiceUtil().getSessionManager().updateSession(open_id, deltaSessionInfo);
				break;
			case ROBOT:
				processRobot(request.getFromUserName(), request.getToUserName(), fileUrl);
				break;
			default:
				break;
			}
		} else {

		}
		long t2 = System.currentTimeMillis();
		logger.info("处理微信用户：{}，图片请求完成，耗时：{}毫秒。", request.getFromUserName(), (t2 - t1));
	}

	/**
	 * 处理链接请求 暂时不支持
	 */
	private void processLinkRequest() {

	}

	/**
	 * 处理地址位置 暂时不支持
	 */
	private void processLocationRequest() {

	}

	/**
	 * 处理关注公众号
	 */
	private void processSubscribeRequest() {
		long t1 = System.currentTimeMillis();
		SubscribeEventRequest request = (SubscribeEventRequest) transfer2Obj(getReqMessage(),
				SubscribeEventRequest.class);
		String fromUserName = request.getFromUserName();
		logger.info("开始处理微信用户：{}关注事件：", fromUserName);
		String welcomeMessage = CSMessageBuilder.createMessage(fromUserName, MessageType.TEXT.getValue(),
				getContext().getServiceUtil().getExpression().getWelcome());
		ICustomerService cs = getContext().getServiceUtil().getCustomerService();
		Map<String, String> userBaseInfo = updateWechatUserInfo(request);
		if (!userBaseInfo.isEmpty()) {
			// 向首次关注微信的用户发送欢迎语
			cs.send(userBaseInfo.get("app_id"), welcomeMessage);
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理微信用户关注公众号事件完成，微信用户：{}，耗时：{}毫秒。", fromUserName, (t2 - t1));
	}

	/**
	 * @param request
	 * @return
	 */
	private Map<String, String> updateWechatUserInfo(MessageRequestBase request) {
		IUserOperationApi userApi = getContext().getServiceUtil().getService(IUserOperationApi.class);
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		logger.info("调用腾讯服务接口获取微信用户：{}基本信息，公众号ID：{}。", request.getFromUserName(), request.getToUserName());
		String app_id = getContext().getAppIdByUserName(request.getToUserName());
		String jsonStr = (String) userApi.queryUserInfo(request.getFromUserName(), request.getToUserName());
		if (jsonStr.contains("errcode")) {
			logger.warn("调用腾讯服务接口获取用户：{}基本信息失败，错误信息：{}。", request.getFromUserName(), GsonUtil.str2Map(jsonStr));
		} else {
			JsonObject jsonObject = GsonUtil.json2JsonObject(jsonStr);
			if (logger.isDebugEnabled()) {
				logger.debug("json2JsonObject：{}.", jsonObject);
			}
			userBaseInfo.put("subscribe", jsonObject.get("subscribe").getAsString());
			userBaseInfo.put("openid", jsonObject.get("openid").getAsString());
			userBaseInfo.put("nickname", jsonObject.get("nickname").getAsString());
			userBaseInfo.put("sex", jsonObject.get("sex").getAsString());
			userBaseInfo.put("city", jsonObject.get("city").getAsString());
			userBaseInfo.put("country", jsonObject.get("country").getAsString());
			userBaseInfo.put("province", jsonObject.get("province").getAsString());
			userBaseInfo.put("headimgurl", jsonObject.get("headimgurl").getAsString());
			userBaseInfo.put("subscribe_time", jsonObject.get("subscribe_time").getAsString());
			userBaseInfo.put("app_id", app_id);
			userBaseInfo.put("update_time", DateUtil.getCurrentDate());
			userBaseInfo.put("update_timestamp", DateUtil.getCurrentTimeMillis());
			// userBaseInfo.put("unionid",
			// jsonObject.get("unionid").getAsString());//关注多个公众号才返回
			userBaseInfo.put("remark", jsonObject.get("remark").getAsString());
			// 0 正常，1 注销
			userBaseInfo.put("state", "0");
			userBaseInfo.put("groupid", jsonObject.get("groupid").getAsString());
			logger.info("获取到微信用户：{}，基本信息：{}。", request.getFromUserName(), userBaseInfo);
			try {
				String result = redis.hmset(IPreferences.WECHAT_USER_PREFIX + request.getFromUserName(), userBaseInfo);
				// 将微信用户统一放入set集合中 2016-10-21 by wangyq
				redis.sadd(IPreferences.WECHAT_USER_SET, IPreferences.WECHAT_USER_PREFIX + request.getFromUserName());
				logger.info("存储微信用户：{}基本信息至Redis，操作结果：{}。", request.getFromUserName(), result);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		return userBaseInfo;
	}

	/**
	 * 处理取消关注公众号
	 */
	private void processUnsubscribeRequest() {
		long t1 = System.currentTimeMillis();
		UnsubscribeEventRequest request = (UnsubscribeEventRequest) transfer2Obj(getReqMessage(),
				UnsubscribeEventRequest.class);
		String fromUserName = request.getFromUserName();
		logger.info("开始处理微信用户：{}取消关注事件：", fromUserName);
		long t2 = System.currentTimeMillis();
		logger.info("处理微信用户：{}取消关注事件，耗时：{}毫秒。", fromUserName, (t2 - t1));
	}

	/**
	 * 处理文本信息西请求
	 */
	private void processTextRequest() {
		long t1 = System.currentTimeMillis();
		TextMessageRequest request = (TextMessageRequest) getMessageRequestBase();
		String fromUserName = request.getFromUserName();
		IMongodbProcessor mongodbProcessor = getContext().getServiceUtil().getMongodbProcessor();
		ICustomerService cs = getContext().getServiceUtil().getCustomerService();
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		// redis操作结果
		String result = null;
		// ----------------------开启全网测试----------------------------
		boolean isReleaseTest = getContext().getServiceUtil().getConfiguration().getBoolean("OMIIS_IS_RELEASE_TEST");
		if (isReleaseTest) {
			logger.info("开启全网发布检测......");
			String toUserName = request.getToUserName();
			String testUserName = "gh_3c884a361561";
			if (testUserName.equals(toUserName)) {
				String content = request.getContent();
				String rspContent = content.split("\\:")[1];
				rspContent += "_from_api";
				logger.info("QUERY_AUTH_CODE：{}。", rspContent);
				String rspMessage = CSMessageBuilder.createMessage(request.getFromUserName(),
						MessageType.TEXT.getValue(), rspContent);
				String appId = getContext().getAppIdByUserName(request.getToUserName());
				logger.info("全网发布测试，appId：{}，通过客服消息接口发送信息：{}。", appId, rspMessage);
				cs.send(appId, rspMessage);
				logger.info("全网发布调用客服消息接口发送消息完成。");
			}
			logger.info("全网发布检测处理完成。");
			return;
		}
		// ----------------------全网测试结束----------------------------
		logger.info("开始处理微信用户：{}请求，格式：文本，内容：{}。", fromUserName, request.getContent());
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		try {
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(fromUserName)));
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		// TODO
		if (userBaseInfo.isEmpty()) {
			updateWechatUserInfo(request);
		}
		if (checkInSession(userBaseInfo)) {
			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			Map<String, String> userSessionInfo = new HashMap<String, String>();
			try {
				userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			String conversation_type = userSessionInfo.get("conversation_type");
			if (StringUtils.isEmpty(conversation_type)) {
				logger.error("微信用户：{}，查询不到会话状态，客户数据丢失。", fromUserName);
				return;
			}

			logger.info("微信用户：{}，会话状态：{}，会话信息：{}。", fromUserName, conversation_type, userSessionInfo);
			ConversationType ct = ConversationType.valueOf(conversation_type.toUpperCase());
			// TODO
			if (ConversationType.ROBOT == ct || ConversationType.CONFIRM_BUSINESS_TYPE == ct) {
				logger.info("微信用户：{}，现在由智能机器人提供服务。", fromUserName);
				if (request.getContent().contains("人工")) {
					sendBusinessType(userSessionInfo);
					Map<String, Object> mongoMessage = new HashMap<>();
					mongoMessage.put("userId", userSessionInfo.get("user_id"));
					mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
					mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
					mongoMessage.put("question", request.getContent());
					mongoMessage.put("robotResponse", "");
					mongoMessage.put("msgType", MessageType.TEXT.toString());
					mongoMessage.put("sendTime", new Date());
					mongoMessage.put("receiveTime", mongoMessage.get("sendTime"));
					mongoMessage.put("createDate", mongoMessage.get("sendTime"));
					try {
						mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				} else {
					processRobot(fromUserName, request.getToUserName(), request.getContent());
				}
				return;
			}
			Map<String, String> msg = new HashMap<String, String>();
			switch (ct) {
			case RESOURCE_REQUEST:
			case EVENT_WAITING:
			case EVENT_WAITING_REPLY:
				TextMessageRequest tmr = request;
				String message = tmr.getContent();
				String content = null;
				if ("2".equals(message)) {
					content = getContext().getServiceUtil().getExpression().getQueueTimeoutTip2();
					// 20161118 update by wangyq，与海鹏约定，客户挂断修改为disconnected
					{
						Map<String, String> tmp = new HashMap<>();
						tmp.putAll(userSessionInfo);
						tmp.put("senderRole", SenderRole.AGENT.toString());
					}
					getMessager().sendMessage(
							createOmiisMessage(userSessionInfo, ConversationType.DISCONNECT.toString(), ""));
					try {
						result = redis.hdel(CacheUtil.getUserKey(userBaseInfo.get("openid")), "session_id");
						userSessionInfo.put("conversation_type", ConversationType.DISCONNECT.toString());
						getContext().getServiceUtil().getSessionManager().removeSession(userBaseInfo.get("openid"));
						cs.send(userBaseInfo.get("app_id"), CSMessageBuilder
								.createMessage(userSessionInfo.get("open_id"), MessageType.TEXT.getValue(), content));
						logger.info("微信用户：{}，选择放弃排队，主动结束本次对话，结束状态：{}，操作结果:{}。", request.getFromUserName(),
								ConversationType.DISCONNECT, result);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					return;
				} else {
					try {
						Map<String, Object> mongoMessage = new HashMap<>();
						mongoMessage.put("userId", userSessionInfo.get("user_id"));
						mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
						mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
						mongoMessage.put("question", request.getContent());
						mongoMessage.put("robotResponse", "");
						mongoMessage.put("msgType", MessageType.TEXT.toString());
						mongoMessage.put("sendTime", new Date());
						mongoMessage.put("receiveTime", mongoMessage.get("sendTime"));
						mongoMessage.put("createDate", mongoMessage.get("sendTime"));
						mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}

					if (!userSessionInfo.containsKey("transferCounter")) {
						userSessionInfo.put("transferCounter", String.valueOf(1));
						// 20161118 update by wangyq
						// 如果微信用户回复非2的关键字，重复发送资源请求，全媒体目前不判断重
						try {
							redis.hmset(CacheUtil.getSessionKey(userBaseInfo.get("session_id")), userSessionInfo);
							logger.info("微信用户：{}，重复发送继续等待请求，更新转接人工统计次数，当前次数：{}。", fromUserName, userSessionInfo);
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
						}
						cs.send(userBaseInfo.get("app_id"),
								CSMessageBuilder.createMessage(userSessionInfo.get("open_id"),
										MessageType.TEXT.getValue(),
										getContext().getServiceUtil().getExpression().getTransferAgentTip2()));
						try {
							Map<String, Object> mongoMessage = new HashMap<>();
							mongoMessage.put("userId", userSessionInfo.get("user_id"));
							mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
							mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
							mongoMessage.put("question", "");
							mongoMessage.put("receiveTime", new Date());
							mongoMessage.put("sendTime", mongoMessage.get("receiveTime"));
							// JsonObject root = new JsonObject();
							// root.addProperty("rspCode", "0");
							// root.addProperty("rspMsg", "");
							// root.addProperty("rspType", "2");
							// root.addProperty("conversationId",
							// userSessionInfo.get("conversationId"));
							// root.addProperty("singleNode", "");
							// JsonObject singleNode = new JsonObject();
							// root.add("singleNode", singleNode);
							// singleNode.addProperty("type", "1");
							// singleNode.addProperty("content",
							// getContext().getServiceUtil().getExpression().getTransferAgentTip2());

							JsonObject root = new JsonObject();
							root.addProperty("protocolId", "6");
							root.addProperty("result", "0");
							root.addProperty("sendTime", "0");
							root.addProperty("answerTypeId", "1");
							JsonObject singleNode = new JsonObject();
							singleNode.addProperty("standardQuestionId", "100");
							singleNode.addProperty("answerMsg",
									getContext().getServiceUtil().getExpression().getTransferAgentTip2());
							singleNode.addProperty("standardQuestion", "");
							singleNode.addProperty("isRichText", "0");
							singleNode.add("list", null);
							root.add("singleNode", singleNode);
							root.add("vagueNode", null);

							mongoMessage.put("robotResponse", root.toString());
							mongoMessage.put("createDate", mongoMessage.get("receiveTime"));
							mongodbProcessor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
						}
					}
				}

			{
				if (ConversationType.EVENT_WAITING.getValue().equals(conversation_type)
						|| ConversationType.EVENT_WAITING_REPLY.getValue().equals(conversation_type)) {
					Map<String, String> deltaSessionInfo = new HashMap<String, String>();
					deltaSessionInfo.put("openId", request.getFromUserName());
					deltaSessionInfo.put("direction", "customer");
					deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
					getContext().getServiceUtil().getSessionManager().updateSession(request.getFromUserName(),
							deltaSessionInfo);
				}
			}
				break;
			case EVENT_TALK:
				if (!userSessionInfo.containsKey("session_valid_flag")) {
					logger.info("将微信用户{}，会话ID：{}设置为有效会话。", request.getFromUserName(), sessionId);
					userSessionInfo.put("session_valid_flag", Boolean.TRUE.toString());
					try {
						redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}
				logger.info("微信用户：{}在会话当中，状态：{}，会话信息：{}，将信息转发至客服，会话内容：{}。", request.getFromUserName(), ct.getValue(),
						userSessionInfo, request.getContent()); {
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("openId", request.getFromUserName());
				deltaSessionInfo.put("direction", "customer");
				deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				getContext().getServiceUtil().getSessionManager().updateSession(request.getFromUserName(),
						deltaSessionInfo);
			}
				getMessager().sendMessage(
						createOmiisMessage(userSessionInfo, MessageType.TEXT.toString(), request.getContent()));
				break;
			case SATISFACTION_SURVEY:
				msg.put("senderId", userSessionInfo.get("sender_id"));
				msg.put("receiverId", userSessionInfo.get("receiverId"));
				msg.put("conversationId", userSessionInfo.get("conversationId"));
				msg.put("msgType", ConversationType.HANGUP.toString());
				userSessionInfo.put("conversation_type", ConversationType.HANGUP.getValue());
				logger.info("微信用户：{}，满意度评价回复内容：{}。", request.getFromUserName(), request.getContent());
				String grade = null;
				try {
					if (StringUtils.isNumeric(request.getContent())) {
						grade = SatisfactionType.getValue(Integer.parseInt(request.getContent())).getValue();
					}
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
				if (!StringUtils.isEmpty(grade)) {
					logger.info("调用全媒体接口更新满意度，微信用户：{}，回复内容：{}。", request.getFromUserName(), request.toString());
					String updateSatisfactionUri = "http://"
							+ WeChatConfiguration.getIngleton().getValue("OMIIS_SERVER_HOST")
							+ ":7003/modifyinfo/investigation/update";
					Map<String, String> reqParams = new HashMap<String, String>();
					reqParams.put("conversationId", userSessionInfo.get("conversationId"));
					reqParams.put("grade", grade);
					// 20161213 update by wangyq更新满意度增加坐席id
					reqParams.put("agentId", userSessionInfo.get("receiverId"));
					executePost(updateSatisfactionUri, reqParams, "");
					try {
						cs.send(userBaseInfo.get("app_id"),
								CSMessageBuilder.createMessage(userSessionInfo.get("open_id"),
										MessageType.TEXT.getValue(),
										getContext().getServiceUtil().getExpression().getThankTip()));
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					logger.info("更新微信用户：{}满意度评价结果：{}。", request.getFromUserName(), request.getContent());
				}
				try {
					getContext().getServiceUtil().getSessionManager().removeSession(request.getFromUserName());
					redis.hdel(CacheUtil.getUserKey(fromUserName), "session_id", "user_id");
					redis.srem(CacheUtil.getAgentKey(userSessionInfo.get("receiverId")), fromUserName);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
				if (StringUtils.isEmpty(grade)) {
					logger.info("微信用户：{}回复满意度序号：{}不正确，转机器人处理。", request.getFromUserName(), request.getContent());
					try {
						redis.hdel(CacheUtil.getUserKey(fromUserName), "session_id");
						redis.srem(CacheUtil.getAgentKey(userSessionInfo.get("receiverId")), fromUserName);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					processRobot(fromUserName, request.getToUserName(), request.getContent());
				}
				logger.info("微信用户：{}在会话当中，会话信息：{}，状态：{}，回复满意度，评价结果：{}，由微信Server端结束本次会话。", request.getFromUserName(),
						ct.getValue(), userSessionInfo, request.getContent());
				break;
			case NO_REPLAY_NOTIFICATION:
				content = request.getContent().trim();
				logger.info("微信用户：{}达到短时间未回复阀值，回复内容：{}。", request.getFromUserName(), content);
				if ("2".equals(content)) {
					msg.put("senderId", userSessionInfo.get("sender_id"));
					msg.put("receiverId", userSessionInfo.get("receiverId"));
					msg.put("conversationId", userSessionInfo.get("conversationId"));
					msg.put("msgType", ConversationType.HANGUP.toString());
					getMessager()
							.sendMessage(createOmiisMessage(userSessionInfo, ConversationType.HANGUP.toString(), ""));
					userSessionInfo.put("conversation_type", ConversationType.HANGUP.getValue());
					getContext().getServiceUtil().getSessionManager().removeSession(request.getFromUserName());
					try {
						result = redis.hdel(CacheUtil.getUserKey(fromUserName), "session_id", "user_id");
						cs.send(userBaseInfo.get("app_id"),
								CSMessageBuilder.createMessage(userSessionInfo.get("open_id"),
										MessageType.TEXT.getValue(),
										getContext().getServiceUtil().getExpression().getHangupTip()));
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					logger.info("微信用户：{}，达到短时间内未回复阀值，选择主动退出会话，注销该用户本次会话，会话信息：{}，回复内容：{}，操作结果：{}。",
							request.getFromUserName(), userSessionInfo, request.getContent(), result);
				} else {
					userSessionInfo.put("previous_message_time", DateUtil.getCurrentDate());
					userSessionInfo.put("previous_message_timestamp", DateUtil.getCurrentTimeMillis());
					userSessionInfo.put("conversation_type", ConversationType.EVENT_TALK.getValue());

					if (!filterChar.equals(content)) {
						getMessager()
								.sendMessage(createOmiisMessage(userSessionInfo, MessageType.TEXT.toString(), content));
					}

					try {
						redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
						{
							Map<String, String> deltaSessionInfo = new HashMap<String, String>();
							deltaSessionInfo.put("openId", request.getFromUserName());
							deltaSessionInfo.put("direction", "customer");
							deltaSessionInfo.put("customer_previous_message_timestamp",
									DateUtil.getCurrentTimeMillis());
							getContext().getServiceUtil().getSessionManager().updateSession(request.getFromUserName(),
									deltaSessionInfo);
						}
						logger.info("微信用户：{}，发送回复内容，会话状态由：{}转为：{}，同时更新会话信息：{}。", fromUserName,
								ConversationType.HANGUP.getValue(), ConversationType.EVENT_TALK.getValue(),
								userSessionInfo);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}
				break;
			default:
				break;
			}
		} else {
			logger.info("微信用户：{}，不在会话状态，优先由智能机器人提供服务。", request.getFromUserName());
			processRobot(fromUserName, request.getToUserName(), request.getContent());
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理微信用户：{}文本请求完成，耗时：{}毫秒。", fromUserName, (t2 - t1));
	}

	/**
	 * 微信用户选择人工，提示微信用户选择业务类型，选择对应技能组 update by wangyq 20170413
	 * 修改技能组提示序号，{@link WeChatContext}，从db加载技能组按order_no排序，在这里偷懒，进行顺序显示
	 *
	 * 
	 * @param userSessionInfo
	 */
	private void sendBusinessType(Map<String, String> userSessionInfo) {
		List<BusinessEntry> businesses = getContext().getBusinesses();
		StringBuffer businessTypeStr = new StringBuffer();
		businessTypeStr.append("回复如下序号，以便为您提供更精准的服务。").append("\n");
		for (int i = 0; i < businesses.size(); i++) {
			BusinessEntry entry = businesses.get(i);
			// businessTypeStr.append(entry.getOrder_no()).append("、").append(entry.getName());
			businessTypeStr.append(i + 1).append("、").append(entry.getName());
			if (i < businesses.size() - 1) {
				businessTypeStr.append("\n");
			}
		}
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		ICustomerService cs = getContext().getServiceUtil().getCustomerService();
		String senderId = userSessionInfo.get("open_id");
		String sessionId = userSessionInfo.get("session_id");
		userSessionInfo.put("previous_message_time", DateUtil.getCurrentDate());
		userSessionInfo.put("previous_message_timestamp", DateUtil.getCurrentTimeMillis());
		userSessionInfo.put("conversation_type", ConversationType.CONFIRM_BUSINESS_TYPE.getValue());
		try {
			String appId = userSessionInfo.get("app_id");
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			String message = CSMessageBuilder.createMessage(senderId, MessageType.TEXT.getValue(),
					businessTypeStr.toString());
			// cs.send(appId, message);

			// processRobot(getMessageRequestBase().getFromUserName(),
			// getMessageRequestBase().getToUserName(),
			// getContext().getAppIdByUserName(getMessageRequestBase().getToUserName()));
			// String appId =
			// getContext().getAppIdByUserName(getMessageRequestBase().getToUserName());
			processRobot(getMessageRequestBase().getFromUserName(), getMessageRequestBase().getToUserName(),
					getMessageRequestBase().getToUserName());
			logger.info("发送待确认业务类型至微信用户：{}，会话ID：{}，更新会话信息：{}，内容：{}。", senderId, sessionId, userSessionInfo,
					businessTypeStr.toString());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	private void processRobot(String openId, String toUserName, String question) {
		MessageType mt = getMessageType();
		String messageType = (mt == MessageType.VOICE ? MessageType.AUDIO.toString() : mt.toString());
		processRobot(openId, toUserName, messageType, question);
	}

	private boolean validWorkDate() {
		Map<String, String> workDayConfig = null;
		try {
			String currentDate = DateUtil.formatDate(new Date(), "yyyyMMdd");
			workDayConfig = getContext().getServiceUtil().getRedisProcessor()
					.hgetall(CacheUtil.getWorkDayKey(currentDate));
			logger.info("当前工作时间：{}，配置信息：{}。", currentDate, workDayConfig);
		} catch (Exception e1) {
			logger.error(e1.getMessage(), e1);
		}
		boolean isWorkingTime = true;
		if (workDayConfig != null && !workDayConfig.isEmpty()) {
			for (Iterator<String> it = workDayConfig.keySet().iterator(); it.hasNext();) {
				String key = it.next();
				String value = workDayConfig.get(key);
				JsonObject root = GsonUtil.json2JsonObject(value);
				if (root == null) {
					isWorkingTime = false;
					break;
				}

				String is_holiday = root.get("is_holiday").getAsString() == null ? ""
						: root.get("is_holiday").getAsString();
				if ("1".equals(is_holiday)) {
					isWorkingTime = false;
					continue;
				}
				JsonElement beginTimeJson = root.get("begin_time");
				JsonElement endTimeJson = root.get("end_time");
				if (beginTimeJson.isJsonNull() || endTimeJson.isJsonNull()) {
					isWorkingTime = false;
					continue;
				}
				String begin_time = beginTimeJson.getAsString();
				String end_time = endTimeJson.getAsString();
				try {
					long beginTime = DateUtil.parseDate(begin_time).getTime();
					long endTime = DateUtil.parseDate(end_time).getTime();
					long currentTime = new Date().getTime();
					if ((currentTime >= beginTime && currentTime <= endTime)) {
						isWorkingTime = true;
						break;
					} else {
						isWorkingTime = false;
					}
				} catch (ParseException e) {
					logger.error(e.getMessage(), e);
				}
			}
		}
		return isWorkingTime;
	}

	/**
	 * 智能机器人处理
	 */
	@SuppressWarnings("rawtypes")
	private void processRobot(String openId, String toUserName, String msgType, String question) {
		long t1 = System.currentTimeMillis();
		logger.info("开始由机器人处理微信用户：{}，请求：{}。", openId, question);
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		ICustomerService cs = getContext().getServiceUtil().getCustomerService();
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		try {
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			logger.info("从缓存获取微信用户：{}，基本信息：{}。", openId, userBaseInfo);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		// step-1 客户入队
		if (StringUtils.isEmpty(sessionId)) {
			// TODO 20170418
			userSessionInfo.putAll(enqueue(toUserName, openId));
			if (question.contains("人工")) {
				sendBusinessType(userSessionInfo);
				return;
			}
		} else {
			try {
				userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		// sessionId = userSessionInfo.get("session_id");
		sessionId = userSessionInfo.get(IPreferences.SESSION_ID_KEY);
		String conversationType = userSessionInfo.get("conversation_type");
		String previousAnswerTypeId = userSessionInfo.get("answerTypeId");
		logger.info("微信用户：{}，会话ID：{}，conversationType：{}，会话信息：{}，机器人上次回复结果：{}。", openId, sessionId, conversationType,
				userSessionInfo, previousAnswerTypeId);
		if (ConversationType.CONFIRM_BUSINESS_TYPE == ConversationType.valueOf(conversationType.toUpperCase())) {
			// if (getContext().getBusinessSeqAndId().containsKey(question)) {
			String appId = getContext().getAppIdByUserName(toUserName);
			if (userSessionInfo.get("app_id").equals(getContext().getAppIdByUserName(toUserName))) {
				// userSessionInfo.put("businessType",
				// getContext().getBusinessIdAndName().get(getContext().getBusinessSeqAndId().get(question)));
				// String appId = getContext().getAppIdByUserName(toUserName);
				userSessionInfo.put("businessType", getContext().getServiceUtil().getConfiguration().getValue(appId));
				// userSessionInfo.put("businessType",
				// getContext().getBusinessIdAndName().get(question));
			} else {
				// TODO 针对客户输入其他选项，未必和其他队列码对应，统一重置为默认的其他业务队列
				logger.info("微信用户：{}回复的业务序号：{}不正确，调整为机器人对话状态。", openId, question);
				userSessionInfo.put("conversation_type", ConversationType.ROBOT.getValue());
				try {
					redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
				processRobot(openId, toUserName, question);
				return;
			}
			logger.info("微信用户：{}，发送申请人工坐席资源请求，序号：{}，业务队列：{}。", openId, question,
					userSessionInfo.get("conversation_type"));
			cs.send(userBaseInfo.get("app_id"), CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
					getContext().getServiceUtil().getExpression().getTransferAgentTip()));
			userSessionInfo.put("conversation_type", ConversationType.RESOURCE_REQUEST.getValue());
			// TODO
			{

			}
			sendResourceRequest(userSessionInfo);
			return;
		}

		if ("3".equals(previousAnswerTypeId) || "1".equals(previousAnswerTypeId) || "0".equals(previousAnswerTypeId)) {
			if ("0".equals(question)) {
				// 20161111 update by wangyq 添加工作时段判断，非工作时段提醒
				// 20170401 update by wangyq 重写工作时间判断
				if (!validWorkDate()) {
					cs.send(userBaseInfo.get("app_id"),
							CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
									getContext().getServiceUtil().getExpression().getRestTimeTip()));
					return;
				}
				String senderId = userSessionInfo.get("open_id");
				logger.info("微信用户：{}申请人工坐席，会话ID：{}，发送待确认业务类型至微信用户。", senderId, sessionId);
				sendBusinessType(userSessionInfo);
				userSessionInfo.put("previous_message_time", DateUtil.getCurrentDate());
				userSessionInfo.put("previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				userSessionInfo.put("conversation_type", ConversationType.CONFIRM_BUSINESS_TYPE.getValue());
				try {
					redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
				return;
			}
		}
		// step-2 访问机器人
		// 再获取一次微信用户信息
		try {
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
		} catch (Exception e1) {
			logger.error(e1.getMessage(), e1);
		}

		if (question.contains("人工")) {
			logger.info("微信用户：{}，发送转人工关键字：{}。", openId, question);
			sendBusinessType(userSessionInfo);
			return;
		}

		IRobotApi robot = getContext().getServiceUtil().getService(IRobotApi.class);
		String conversationId = userSessionInfo.get("conversationId");
		// 20161024 update by wangyq 访问机器人获取conversationId，用于调用机器人接口凭证
		String userId = userSessionInfo.get("user_id");
		logger.info("微信用户：{}，userId：{}，基本信息：{}。", openId, userId, userBaseInfo);
		if (StringUtils.isEmpty(conversationId)) {
			String conversationIdResult = null;
			String code = "0";
			try {
				conversationIdResult = (String) robot.getConversationId(userId,
						getContext().getServiceUtil().getExpression().getWelcome(), IPreferences.CHANNEL_ID);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			logger.info("会话ID不存在，调用机器人接口创建会话ID，结果：{}。", conversationIdResult);
			JsonObject conversationJson = null;
			if (!StringUtils.isEmpty(conversationIdResult)) {
				conversationJson = GsonUtil.json2JsonObject(conversationIdResult);
				code = conversationJson.get("code").getAsString();
				if ("0".equals(code)) {
					conversationId = conversationJson.getAsJsonObject("map").get("conversationId").getAsString();
					logger.info("用户：{}申请会话ID成功，conversationId：{}。", openId, conversationId);
				} else {
					// TODO 申请ID失败，如何做后续操作？
					logger.error("获取会话ID失败！");
				}
			} else {
				String answerTypeId = "1";
				String answerMsg = null;
				StringBuffer messageBuffer = new StringBuffer();
				String endWords = getContext().getServiceUtil().getExpression().getRobotEndWords();
				answerMsg = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
						messageBuffer.append(endWords).toString());
				logger.error("智能机器人返回信息异常，回复微信用户：{},内容：{}。", openId, answerMsg);
				cs.send(userBaseInfo.get("app_id"), answerMsg);
				userSessionInfo.put("answerTypeId", answerTypeId);
				try {
					redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
				return;
			}
		}

		{
			// 公众号昵称，根据昵称获取本地配置文件中的机器人路由id
			// 配置文件详见./config/routing.properties 公众号昵称=机器人路由ID
			logger.info("公众号ID：{}，基本信息：{}。", userBaseInfo.get("app_id"),
					getContext().getCompanyInfo(CacheUtil.getCompanyKey(userBaseInfo.get("app_id"))));
			String routingId = getContext().getServiceUtil().getConfiguration().getValue(userBaseInfo.get("app_id"));
			logger.info("公众号：{}，机器人路由：{}。", userBaseInfo.get("app_id"), routingId);
			String result = (String) robot.query2(userId, openId, question, conversationId, IPreferences.CHANNEL_ID,
					routingId);
			String rspCode = "0";
			JsonObject answertObject = null;
			if (!StringUtils.isEmpty(result)) {
				answertObject = GsonUtil.json2JsonObject(result);
				rspCode = answertObject.get("code").getAsString();
			} else {
				rspCode = "1";
			}
			String answerTypeId = "6";
			String answerMessage = "";
			StringBuffer messageBuffer = new StringBuffer();
			if (!"0".equals(rspCode)) {
				answerTypeId = "1";
				answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(), messageBuffer
						.append(getContext().getServiceUtil().getExpression().getRobotEndWords()).toString());
				logger.error("智能机器人返回信息异常，回复微信用户：{}，公众号：{}，信息：{}。", openId, toUserName, answerMessage);
			} else {
				String detailAnswerStr = answertObject.getAsJsonObject("map").getAsJsonPrimitive("robotResponse")
						.getAsString();
				if (StringUtils.isEmpty(detailAnswerStr)) {
					logger.error("调用机器人问题接口异常。");
					answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(), messageBuffer
							.append(getContext().getServiceUtil().getExpression().getRobotEndWords()).toString());
					answerTypeId = "1";
				} else {
					JsonObject detailAnswerObject = GsonUtil.json2JsonObject(detailAnswerStr);
					answerTypeId = detailAnswerObject.getAsJsonPrimitive("answerTypeId").getAsString();
					logger.info("智能机器人返回结果：{}，AnswerTypeId：{}。", detailAnswerStr, answerTypeId);
					switch (answerTypeId) {
					case "1":
					case "2":
					case "3":
					case "7":
						// 统一提示转人工1、系统错误，2、敏感词，3、无法回答，7、没有答案
						JsonObject singleNodeObject = detailAnswerObject.getAsJsonObject("singleNode");
						answerMessage = singleNodeObject.getAsJsonPrimitive("answerMsg").getAsString();
						messageBuffer.append(answerMessage).append("\n")
								.append(getContext().getServiceUtil().getExpression().getRobotEndWords2());
						answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
								messageBuffer.toString());
						break;
					case "4":
						// 需要补问
						singleNodeObject = detailAnswerObject.getAsJsonObject("singleNode");
						answerMessage = singleNodeObject.getAsJsonPrimitive("answerMsg").getAsString();
						answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
								answerMessage);
						break;
					case "5":
						// 多选问题
						JsonObject vagueNodeObject = detailAnswerObject.getAsJsonObject("vagueNode");
						JsonArray itemListJsonArray = vagueNodeObject.getAsJsonArray("itemList");
						String promptVagueMsg = vagueNodeObject.getAsJsonPrimitive("promptVagueMsg").getAsString();
						String endVagueMsg = vagueNodeObject.getAsJsonPrimitive("endVagueMsg").getAsString();
						StringBuffer messageBF = new StringBuffer();
						messageBF.append(promptVagueMsg).append("\n");
						for (int i = 0; i < itemListJsonArray.size(); i++) {
							JsonElement e = itemListJsonArray.get(i);
							JsonObject ee = e.getAsJsonObject();
							String num = ee.getAsJsonPrimitive("num").getAsString();
							question = ee.getAsJsonPrimitive("question").getAsString();
							messageBF.append(num).append("、").append(question).append("\n");
						}
						messageBF.append(endVagueMsg);
						answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
								messageBF.toString());
						break;
					case "6":
					case "8":
						singleNodeObject = detailAnswerObject.getAsJsonObject("singleNode");
						String isRichText = singleNodeObject.getAsJsonPrimitive("isRichText").getAsString();
						if ("0".equals(isRichText)) {
							answerMessage = singleNodeObject.getAsJsonPrimitive("answerMsg").getAsString();
							answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
									answerMessage);
						} else {
							JsonArray newsList = singleNodeObject.getAsJsonArray("list");
							List<String> news = new ArrayList<>();
							for (int i = 0; i < newsList.size(); i++) {
								JsonElement e = newsList.get(i);
								JsonObject ee = e.getAsJsonObject();
								String title = ee.getAsJsonPrimitive("title").getAsString();
								String description = ee.getAsJsonPrimitive("description").getAsString();
								String picurl = ee.getAsJsonPrimitive("picurl").getAsString();
								String url = ee.getAsJsonPrimitive("url").getAsString();
								news.add(title);
								news.add(description);
								news.add(picurl);
								news.add(url);
							}
							answerMessage = CSMessageBuilder.createMessage(openId, MessageType.NEWS.getValue(),
									news.toArray(new String[] {}));
						}
						break;
					case "10":
						singleNodeObject = detailAnswerObject.getAsJsonObject("singleNode");
						answerMessage = singleNodeObject.getAsJsonPrimitive("answerMsg").getAsString();
						answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
								answerMessage);
						logger.warn("智能机器人遭访问攻击，如何处理？");
						break;
					case "11":
						singleNodeObject = detailAnswerObject.getAsJsonObject("singleNode");
						answerMessage = singleNodeObject.getAsJsonPrimitive("answerMsg").getAsString();
						answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
								answerMessage);
						logger.info("智能机器人提示聊天过频。");
						break;
					case "12":
						// 多选问题
						vagueNodeObject = detailAnswerObject.getAsJsonObject("vagueNode");
						itemListJsonArray = vagueNodeObject.getAsJsonArray("itemList");
						promptVagueMsg = vagueNodeObject.getAsJsonPrimitive("promptVagueMsg").getAsString();
						endVagueMsg = vagueNodeObject.getAsJsonPrimitive("endVagueMsg").getAsString();
						messageBF = new StringBuffer();
						messageBF.append(promptVagueMsg).append("\n");
						for (int i = 0; i < itemListJsonArray.size(); i++) {
							JsonElement e = itemListJsonArray.get(i);
							JsonObject ee = e.getAsJsonObject();
							String num = ee.getAsJsonPrimitive("num").getAsString();
							question = ee.getAsJsonPrimitive("question").getAsString();
							messageBF.append(num).append("、").append(question).append("\n");
						}
						messageBF.append(endVagueMsg);
						answerMessage = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
								messageBF.toString());
						break;
					default:
						break;
					}
				}
			}
			cs.send(userBaseInfo.get("app_id"), answerMessage);
			userSessionInfo.put("conversationId", conversationId);
			userSessionInfo.put("answerTypeId", answerTypeId);
		}
		try {
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		long t2 = System.currentTimeMillis();
		logger.info("智能机器人处理微信用户：{}请求完成，会话ID：{}，更新会话信息：{}，耗时：{}毫秒。", openId, CacheUtil.getSessionKey(sessionId),
				userSessionInfo, (t2 - t1));
	}

	/**
	 * 创建全媒体格式的消息-发送人工坐席
	 * 
	 * @param userSessionInfo
	 * @param messageType
	 * @param msgContent
	 * @return
	 */
	private Map<String, String> createOmiisMessage(Map<String, String> userSessionInfo, String messageType,
			String msgContent) {
		Map<String, String> message = new HashMap<String, String>(userSessionInfo);
		message.putAll(userSessionInfo);
		message.put("msgType", messageType);
		message.put("msgContent", msgContent);
		logger.info("微信用户：{}发送信息至坐席，会话信息：{}，转换成全媒体格式消息：{}。", userSessionInfo.get("open_id"), userSessionInfo, message);
		return message;
	}

	/**
	 * 申请人工坐席
	 * 
	 * @param userSessionInfo
	 */
	private void sendResourceRequest(Map<String, String> userSessionInfo) {
		long t1 = System.currentTimeMillis();
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		String senderId = userSessionInfo.get("open_id");
		String sessionId = userSessionInfo.get(IPreferences.SESSION_ID_KEY);
		Map<String, String> message = createOmiisMessage(userSessionInfo, ConversationType.RESOURCE_REQUEST.toString(),
				userSessionInfo.get("businessType"));
		logger.info("微信用户：{}，申请人工坐席资源，会话ID：{}，会话信息：{}，内容：{}。", senderId, sessionId, userSessionInfo, message);
		IOmiisMessager messager = getContext().getServiceUtil().getOmiisMessager();
		messager.sendMessage(message);
		userSessionInfo.put("previous_message_time", DateUtil.getCurrentDate());
		userSessionInfo.put("previous_message_timestamp", DateUtil.getCurrentTimeMillis());
		userSessionInfo.put("request_resource_timestamp", userSessionInfo.get("previous_message_timestamp"));
		try {
			{
				{
					Map<String, String> deltaSessionInfo = new HashMap<String, String>();
					deltaSessionInfo.put("openId", senderId);
					deltaSessionInfo.put("agentId", "");
					deltaSessionInfo.put("direction", "customer");
					deltaSessionInfo.put("customer_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
					deltaSessionInfo.put("agent_previous_message_timestamp",
							deltaSessionInfo.get("customer_previous_message_timestamp"));
					getContext().getServiceUtil().getSessionManager().updateSession(senderId, deltaSessionInfo);
				}
			}
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		long t2 = System.currentTimeMillis();
		logger.info("发送申请人工坐席资源请求完成，耗时：{}毫秒。", (t2 - t1));
	}

	/**
	 * 微信客户入队
	 * 
	 * @param user_name
	 * @param open_id
	 * @return
	 */
	public synchronized Map<String, String> enqueue(String user_name, String open_id) {
		long t1 = System.currentTimeMillis();
		String queue_seq = "queue_seq";
		logger.info("公众号：{}，微信用户：{}进入会话......", user_name, open_id);
		IRedisProcessor processor = getContext().getServiceUtil().getRedisProcessor();
		String session_id = "1000000";
		String user_id = null;
		{
			try {
				session_id = processor.incr(queue_seq);
				long t11 = System.currentTimeMillis();
				String uri = "http://" + getContext().getServiceUtil().getConfiguration().getValue("OMIIS_SERVER_HOST")
						+ ":7003/visitor/init";
				String resultJson = executePost(uri, "", "");
				logger.info("调用全媒体接口获取微信用户：{}的user_id，接口地址：{}。", open_id, uri);
				if (StringUtils.isEmpty(resultJson)) {
					user_id = session_id;
					logger.info("获取全媒体user_id失败，用session_id代替，{}。", user_id);
				} else {
					user_id = GsonUtil.json2JsonObject(resultJson).getAsJsonPrimitive("id").getAsString();
				}
				logger.info("微信用户：{},获取user_id：{}，耗时：{}毫秒。", open_id, user_id, (System.currentTimeMillis() - t11));
			} catch (Exception e) {
				user_id = session_id;
				logger.error("从全媒体获取user_id失败：" + e.getMessage(), e);
			}
		}

		// 20170420 添加获取conversationId，麦子需求：直接输入人工关键字，转入人工
		// TODO

		// TODO user_id 此处有问题，后续改正 20160809 by wangyq
		logger.info("微信用户：{},user_id：{}，会话ID：{}。", open_id, user_id, session_id);
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		// 是否可以进入queue
		boolean isEnqueue = true;
		{
			// TODO
			try {
				userBaseInfo.putAll(processor.hgetall(CacheUtil.getUserKey(open_id)));
			} catch (Exception e1) {
				logger.error(e1.getMessage(), e1);
			}
			String previous_sync_timestamp = userBaseInfo.get("previous_sync_timestamp");
			String previous_sync_time = userBaseInfo.get("previous_sync_time");
			boolean isSync = false;
			if (StringUtils.isEmpty(previous_sync_timestamp) || StringUtils.isEmpty(previous_sync_time)) {
				isSync = true;
			} else {
				long currentTimestamp = System.currentTimeMillis();
				// 按天从腾讯获取微信用户基本信息，刷新微信用户基本信息
				if ((currentTimestamp - Long.parseLong(previous_sync_timestamp)) > 24 * 3600 * 1000) {
					isSync = true;
				}
			}

			logger.info("微信用户：{}，同步信息标志：{}，基本信息：{}。", open_id, isSync, userBaseInfo);
			if (userBaseInfo.isEmpty() || isSync) {
				logger.info("获取微信用户：{}信息失败请确认Redis是否可用？，调用腾讯服务接口获取微信用户基本信息，公众号ID：{}。", open_id, user_name);// user_name
				userBaseInfo.putAll(updateWechatUserInfo(getMessageRequestBase()));
				isEnqueue = !userBaseInfo.isEmpty();
			}
			if (isEnqueue) {
				userBaseInfo.put("session_id", session_id);
				userBaseInfo.put("user_id", user_id);
				logger.info("微信用户：{}，基本信息：{}。", open_id, userBaseInfo);
				try {
					// 将微信用户统一放入set集合中 2016-10-21 by wangyq
					String result = processor.hmset(CacheUtil.getUserKey(open_id), userBaseInfo);
					processor.sadd(IPreferences.WECHAT_USER_SET, CacheUtil.getUserKey(open_id));
					processor.set(user_id, open_id);
					logger.info("微信用户open_id：{}，userId：{}绑定，同时更新基本信息：{}，操作结果：{}。", open_id, user_id, userBaseInfo,
							result);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}

				userSessionInfo.put("session_id", session_id);
				userSessionInfo.put("sender_name",
						userBaseInfo.get("nickname") == null ? user_id : userBaseInfo.get("nickname"));
				userSessionInfo.put("app_id", userBaseInfo.get("app_id"));
				// 20170106 update by wangyq 注释
				// userSessionInfo.put("queue_id", queue_id);
				userSessionInfo.put("user_id", user_id);
				userSessionInfo.put("open_id", open_id);
				userSessionInfo.put("request_time", DateUtil.getCurrentDate());
				userSessionInfo.put("request_timestamp", DateUtil.getCurrentTimeMillis());
				userSessionInfo.put("status", "1");
				userSessionInfo.put("previous_message_time", userSessionInfo.get("request_time"));
				userSessionInfo.put("previous_message_timestamp", userSessionInfo.get("request_timestamp"));
				userSessionInfo.put("sender_id", open_id);
				userSessionInfo.put("conversation_type", ConversationType.ROBOT.getValue());

				{
					IRobotApi robot = getContext().getServiceUtil().getService(IRobotApi.class);
					String conversationId = userSessionInfo.get("conversationId");
					// 20161024 update by wangyq
					// 访问机器人获取conversationId，用于调用机器人接口凭证
					String userId = userSessionInfo.get("user_id");
					logger.info("微信用户：{}，userId：{}，基本信息：{}。", open_id, userId, userBaseInfo);
					if (StringUtils.isEmpty(conversationId)) {
						String conversationIdResult = null;
						String code = "0";
						try {
							conversationIdResult = (String) robot.getConversationId(userId,
									getContext().getServiceUtil().getExpression().getWelcome(),
									IPreferences.CHANNEL_ID);
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
						}
						logger.info("会话ID不存在，调用机器人接口创建会话ID，结果：{}。", conversationIdResult);
						JsonObject conversationJson = null;
						if (!StringUtils.isEmpty(conversationIdResult)) {
							conversationJson = GsonUtil.json2JsonObject(conversationIdResult);
							code = conversationJson.get("code").getAsString();
							if ("0".equals(code)) {
								conversationId = conversationJson.getAsJsonObject("map").get("conversationId")
										.getAsString();
								userSessionInfo.put("conversationId", conversationId);
								logger.info("用户：{}申请会话ID成功，conversationId：{}。", open_id, conversationId);
							} else {
								// TODO 申请ID失败，如何做后续操作？
								logger.error("获取会话ID失败！");
							}
						}
						try {
							String result = processor.hmset(CacheUtil.getSessionKey(session_id), userSessionInfo);
							// 将微信用户sessionId存入redis set中
							processor.sadd(IPreferences.WECHAT_QUEUE_SET, CacheUtil.getSessionKey(session_id));
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
						}
					}
				}
			}
		}
		long t2 = System.currentTimeMillis();
		logger.info("微信用户：{}进入会话，结果：{}，会话ID：{}，会话信息：{}，耗时：{}毫秒。", open_id, Boolean.toString(isEnqueue), session_id,
				userSessionInfo, (t2 - t1));
		return userSessionInfo;
	}
}
